#include <QMessageBox>
#include <QDir>
#include <QFileDialog>
#include <QDebug>
#include <QPainter>
#include <QtMath>

#include "mainwindow.h"
#include "ui_mainwindow.h"

// #include "dwgobject.h"
#include "dwgpoint.h"
#include "dwgline.h"
#include "dwgcircle.h"
#include "dwgrectangle.h"
#include "dwgarc.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // 下面这段用于设置File子页面中的布局和控件的位置
    ui->tabWidget->setFixedHeight(80);     // 设置QTabWidget控件的高度

    ui->FileHLayout->setAlignment(Qt::AlignLeft); // 把File子页面中的布局设计左对齐
    ui->FileHLayout->setAlignment(Qt::AlignTop);  // 把File子页面中的布局设计上对齐
    ui->FileHLayout->setContentsMargins(0,0,0,0);  // 设置布局与子页面四边的间距为0
    ui->FileHLayout->setSpacing(0);                // 设置布局中各控件之间的间距为0

    //  下面的代码，把在UI中添加的QToolButton控件与QAction动作连接起来
    ui->NewTB->setDefaultAction(ui->actionNew);
    ui->OpenTB->setDefaultAction(ui->actionOpen);
    ui->SaveTB->setDefaultAction(ui->actionSave);
    ui->SaveAsTB->setDefaultAction(ui->actionSaveAs);
    ui->ExitTB->setDefaultAction(ui->actionExit);

    ui->FileTab->setLayout(ui->FileHLayout);		// 通过本语句让布局布满Tab子页面


    //实现DrawTB子页面的按钮
    QHBoxLayout *drawHL1 = new QHBoxLayout;               // 我们先设计一个横排列的布局，用于排列绘图控件
    drawHL1->setAlignment(Qt::AlignLeft);					//  左对齐
    drawHL1->setAlignment(Qt::AlignTop);                       //  顶对齐
    drawHL1->setContentsMargins(0,0,0,0);				     //  四边距为0
    drawHL1->setSpacing(0);                                  //  内部控件间距为0

    // 下面这一段代码主要用于设计一个QToolButton类型的按钮控件，并把它添加到布局中
    QToolButton *pointTB = new QToolButton;                     // 第一个控件，画点
    pointTB->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);        // 控件样式设计为只显示图标
    pointTB->setFixedSize(QSize(32,32));                         // 指定图标的大小为 32x32 像素
    pointTB->setText("Point");                                  // 同时也设置了控件的显示名称
    pointTB->setArrowType(Qt::NoArrow);                         // 设置为没有箭头显示
    const QIcon pointIcon = QIcon::fromTheme("Point", QIcon(":/icon/icons/ico/Curve points.ico")); //资源文件中的点图标
    pointTB->setIcon(pointIcon);                                // 把这个点的图标设置给QToolButton按钮
    connect(pointTB, &QToolButton::clicked, this, &MainWindow::pointTB_clicked); // 建立点击该按钮的槽函数的链接
    drawHL1->addWidget(pointTB);                                // 把这个按钮添加到布局中

    // 最后，把DrawTab的布局设计成刚才创建的布局
    ui->DrawTab->setLayout(drawHL1);

    // 下面这一段代码主要用于设计一个画线的按钮控件，并把它添加到布局中
    QToolButton *lineTB = new QToolButton;                     // 第一个控件，画点
    lineTB->setToolButtonStyle(Qt::ToolButtonIconOnly);        // 控件样式设计为只显示图标
    lineTB->setFixedSize(QSize(32,32));                         // 指定图标的大小为 32x32 像素
    lineTB->setText("Line");                                  // 同时也设置了控件的显示名称
    lineTB->setArrowType(Qt::NoArrow);                         // 设置为没有箭头显示
    const QIcon lineIcon = QIcon::fromTheme("Line", QIcon(":/icon/icons/ico/Line.ico")); // 资源文件中的线的图标
    lineTB->setIcon(lineIcon);                                // 把这个点的图标设置给QToolButton按钮
    connect(lineTB,&QToolButton::clicked,this,&MainWindow::lineTB_clicked);   // 建立点击该按钮的槽函数的链接
    drawHL1->addWidget(lineTB);                                // 把这个按钮添加到布局中

    // 下面这一段代码主要用于设计一个画圆的按钮控件，并把它添加到布局中
    QToolButton *circleTB = new QToolButton;                     // 第一个控件，画点
    circleTB->setToolButtonStyle(Qt::ToolButtonIconOnly);        // 控件样式设计为只显示图标
    circleTB->setFixedSize(QSize(32,32));                         // 指定图标的大小为 32x32 像素
    circleTB->setText("Circle");                                  // 同时也设置了控件的显示名称
    circleTB->setArrowType(Qt::NoArrow);                         // 设置为没有箭头显示
    circleTB->setPopupMode(QToolButton::MenuButtonPopup);
    const QIcon circleIcon = QIcon::fromTheme("Circle", QIcon(":/icon/icons/ico/Circle.ico")); // 资源文件中的线的图标
    circleTB->setIcon(circleIcon);                                // 把这个点的图标设置给QToolButton按钮

    QMenu * circleMenu = new QMenu;               // 为以叠加图标，需要构建菜单再添加动作
    QAction * cirAct1 = new QAction(QIcon(":/icon/icons/ico/Circle.ico"),"圆心半径");
    QAction * cirAct2 = new QAction(QIcon(":/icon/icons/ico/Circle.ico"),"两点画圆");
    QAction * cirAct3 = new QAction(QIcon(":/icon/icons/ico/Circle.ico"),"三点画圆");
    circleMenu->addAction(cirAct1);
    circleMenu->addAction(cirAct2);
    circleMenu->addAction(cirAct3);
    circleTB->setMenu(circleMenu);              		// 把菜单添加到QToolButton

    connect(circleTB,&QToolButton::clicked,this,&MainWindow::circleTB_clicked);   // 建立点击该按钮的槽函数的链接
    drawHL1->addWidget(circleTB);        // 把这个按钮添加到布局中

    // 下面这一段代码主要用于设计一个画矩形的按钮控件，并把它添加到布局中
    QToolButton *rectangleTB = new QToolButton;                     // 第一个控件，画点
    rectangleTB->setToolButtonStyle(Qt::ToolButtonIconOnly);        // 控件样式设计为只显示图标
    rectangleTB->setFixedSize(QSize(32,32));                         // 指定图标的大小为 32x32 像素
    rectangleTB->setText("Rectangle");                                  // 同时也设置了控件的显示名称
    rectangleTB->setArrowType(Qt::NoArrow);                         // 设置为没有箭头显示
    const QIcon squareIcon = QIcon::fromTheme("Rectangle", QIcon(":/icon/icons/ico/Square.ico")); // 资源文件中的线的图标
    circleTB->setIcon(squareIcon);                                // 把这个点的图标设置给QToolButton按钮
    connect(circleTB,&QToolButton::clicked,this,&MainWindow::rectangleTB_clicked);   // 建立点击该按钮的槽函数的链接
    drawHL1->addWidget(circleTB);                                // 把这个按钮添加到布局中

    // 下面这一段代码主要用于设计一个画矩形的按钮控件，并把它添加到布局中
    QToolButton *arcTB = new QToolButton;                     // 第一个控件，画点
    arcTB->setToolButtonStyle(Qt::ToolButtonIconOnly);        // 控件样式设计为只显示图标
    arcTB->setFixedSize(QSize(32,32));                         // 指定图标的大小为 32x32 像素
    arcTB->setText("Arc");                                  // 同时也设置了控件的显示名称
    arcTB->setArrowType(Qt::NoArrow);                         // 设置为没有箭头显示
    const QIcon arcIcon = QIcon::fromTheme("Arc", QIcon(":/icon/icons/ico/Arc.ico")); // 资源文件中的线的图标
    arcTB->setIcon(arcIcon);                                // 把这个点的图标设置给QToolButton按钮
    connect(arcTB,&QToolButton::clicked,this,&MainWindow::arcTB_clicked);   // 建立点击该按钮的槽函数的链接
    drawHL1->addWidget(arcTB);                                // 把这个按钮添加到布局中

    // 为了布局DrawTab中的图标，再创建一个总的横向布局，把前面的三个布局都添加进来，
    QHBoxLayout *drawHL = new QHBoxLayout;
    drawHL->setAlignment(Qt::AlignLeft);
    drawHL->setAlignment(Qt::AlignTop);
    drawHL->setContentsMargins(0,0,0,0);

    drawHL->addLayout(drawHL1);
    // drawHL->addLayout(drawVL1);
    // drawHL->addLayout(drawHL3);
    // drawHL->addLayout(drawHL4);

    // 最后，把DrawTab的布局设计成刚才创建的布局
    ui->DrawTab->setLayout(drawHL);

}


MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_actionExit_triggered()
{
    // 退出程序之前，需要检查文件是否保存，我们将在以后的学习中添加代码
    this->close();   //  退出窗口应用程序
}

void MainWindow::on_actionNew_triggered()
{
    //新建一个文件，也就是要把主链表清空，但在此之前，提示用户是否保存
    int ret = QMessageBox::warning(this, "Warning",
                                   "你的图形是否保存?",
                                   QMessageBox::Ok | QMessageBox::Cancel);
    if(ret == QMessageBox::Ok)
        m_MainList.clear();
}

void MainWindow::on_actionOpen_triggered()
{
    // 打开一个文件之前，也需要判断是否保存当前文件，我们将在以后的学习中添加
    QString curPath = QDir::currentPath();   // 获得当前程序所在的目录
    QString aFileName = QFileDialog::getOpenFileName(this,"选择一个图形文件",curPath,"CAD文件(*.*)");
    if(!aFileName.isEmpty())
        qDebug()<<"把文件内容读入到m_MainList中";
}

void MainWindow::on_actionSave_triggered()
{
    // 保存一个文件
    QString curPath = QDir::currentPath();
    QString aFileName = QFileDialog::getSaveFileName(this,"输入一个图形文件名称",curPath,"CAD文件(*.*)");
    if(!aFileName.isEmpty())
        qDebug()<<"把m_MainList中的对象写入到 : "<< aFileName;
}

void MainWindow::on_actionSaveAs_triggered()
{
    // 另存一个文件
    QString curPath = QDir::currentPath();
    QString aFileName = QFileDialog::getSaveFileName(this,"输入一个图形文件名称",curPath,"CAD文件(*.*)");
    if(!aFileName.isEmpty())
        qDebug()<<"把m_MainList中的对象写入到 : "<< aFileName;
}


// 绘图槽函数
    // 选择绘图类型
void MainWindow::pointTB_clicked()
{
    curDrawType = DPoint;
}

void MainWindow::lineTB_clicked()
{
    curDrawType = DPoint;
}


void MainWindow::circleTB_clicked()
{
    curDrawType = DCircle;
}


void MainWindow::rectangleTB_clicked()
{
    curDrawType = DRectangle;
}


void MainWindow::arcTB_clicked()
{
    curDrawType = DArc;
}


void MainWindow::pLineTB_clicked()
{
    curDrawType = DPLine;
}


void MainWindow::splineTB_clicked()
{
    curDrawType = DSpline;
}


void MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);

    for(auto i: m_MainList)
        i->Draw(&painter);
}



DrawType mCurDrawType = None;		// 用于记录当前正在绘制哪种图元
bool isFirst = true;                     //  用于记录当前鼠标是否是第一点
QPoint temppt;                        //  用于记录临时的点


void MainWindow::mousePressEvent(QMouseEvent *event)
{
    QPoint currentPoint = event->pos();

    switch (mCurDrawType)
    {
    case DLine:
        if (isFirst)
        {
            temppt = currentPoint;
            isFirst = false;
        }
        else
        {
            DwgLine *line = new DwgLine;
            line->mStartPt = temppt;
            line->mEntPt = currentPoint;
            line->mType = DLine;        //再次定义line的类型，若没有在子类中定义则覆盖默认的父类中的None。
            m_MainList.append(line);
            isFirst = true;
            update();
        }
        break;
    case DPoint:
    {
        DwgPoint *point = new DwgPoint;
        point->mPoint = currentPoint;
        point->mType = DPoint;
        m_MainList.append(point);
        update();
        break;
    }
    case DCircle:
        if (isFirst)
        {
            temppt = currentPoint;
            isFirst = false;
        }
        else
        {
            DwgCircle *circle = new DwgCircle;
            circle->mCenterPt = temppt;
            QPointF currentPointF(currentPoint);
            QPointF tempPointF(temppt);
            qreal radius = qSqrt((currentPointF.x() - tempPointF.x()) * (currentPointF.x() - tempPointF.x()) + (currentPointF.y() - tempPointF.y()) * (currentPointF.y() - tempPointF.y()));
            circle->mRadius = radius;
            circle->mType = DCircle;
            m_MainList.append(circle);
            isFirst = true;
            update();
        }
        break;
    case DRectangle:
        if (isFirst)
        {
            temppt = currentPoint;
            isFirst = false;
        }
        else
        {
            DwgRectangle *rectangle = new DwgRectangle;
            rectangle->mTopLeft = temppt;
            rectangle->mBottomRight = currentPoint;
            rectangle->mType = DRectangle;
            m_MainList.append(rectangle);
            isFirst = true;
            update();
        }
        break;
    case DArc:
        if (isFirst)
        {
            temppt = currentPoint;
            isFirst = false;
        }
        else
        {
            DwgArc *arc = new DwgArc;
            arc->mCenter = temppt;
            QPointF currentPointF(currentPoint);
            QPointF tempPointF(temppt);
            qreal radius = qSqrt((currentPointF.x() - tempPointF.x()) * (currentPointF.x() - tempPointF.x()) + (currentPointF.y() - tempPointF.y()) * (currentPointF.y() - tempPointF.y()));
            arc->mRadius = radius;
            arc->mStartAngle = 0;  // 假设起始角度为0
            arc->mSpanAngle = 180; // 假设跨度角度为180度
            arc->mType = DArc;
            m_MainList.append(arc);
            isFirst = true;
            update();
        }
        break;
    case None:
        // 处理 None 的情况，或者什么都不做
        break;
    default:
        // 处理其他未预料到的情况
        break;
    }
}
